package com.auto.survey.measurecontroller

import android.util.Log
import com.auto.survey.activity.monitoring.entity.MonitoringPointCtrlObservation
import com.auto.survey.measurecontroller.entity.MeasureConfig
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import java.text.SimpleDateFormat
import java.util.Date

class MeasurementDataProcessor (
    private val dateFormat: SimpleDateFormat,
    private val listener: MeasureProcessListener?
) {
    private val TAG = MeasurementDataProcessor::class.java.simpleName
    /**
     * 解析测量结果为观测值对象
     */
    fun parseObservationResult(
        pointCode: String,
        resultData: String,
        isLeft: Boolean,
        pointId: Int
    ): MonitoringPointCtrlObservation {
        return try {
            Log.i(TAG, "resultData = $resultData")
            val parsedData = Gson().fromJson<List<String>>(
                resultData,
                object : TypeToken<List<String>>() {}.type
            )

            Log.i(TAG, "parsedData size = ${parsedData.size}")

            val horizontalAngle = parsedData[1].toDouble()
            val verticalAngle = parsedData[2].toDouble()
            val distance = parsedData[3].toDoubleOrNull()

            if (isLeft) {
                MonitoringPointCtrlObservation(
                    monitoringPointId = pointId,
                    observationTime = dateFormat.format(Date()),
                    horizontalAngleL = horizontalAngle,
                    verticalAngleL = verticalAngle,
                    distanceL = distance,
                    horizontalAngleR = null,
                    verticalAngleR = null,
                    distanceR = null,
                    measure2C = null,
                    measure2D = null
                )
            } else {
                MonitoringPointCtrlObservation(
                    monitoringPointId = pointId,
                    observationTime = dateFormat.format(Date()),
                    horizontalAngleL = null,
                    verticalAngleL = null,
                    distanceL = null,
                    horizontalAngleR = horizontalAngle,
                    verticalAngleR = verticalAngle,
                    distanceR = distance,
                    measure2C = null,
                    measure2D = null
                )
            }
        } catch (e: JsonSyntaxException) {
            Log.e("DataProcessor", "解析测量结果失败: ${e.message}", e)
            MonitoringPointCtrlObservation(
                monitoringPointId = pointId,
                observationTime = dateFormat.format(Date()),
                horizontalAngleL = null,
                verticalAngleL = null,
                distanceL = null,
                horizontalAngleR = null,
                verticalAngleR = null,
                distanceR = null,
                measure2C = null,
                measure2D = null
            )
        }
    }

    /**
     * 计算观测值的2C和2D互差
     */
    fun calculateObservationDifferences(observations: List<MonitoringPointCtrlObservation>) {
        if (observations.size < 2) return

        val firstObs = observations[0]
        val secondObs = observations[1]

        // 确定哪个是盘左哪个是盘右
        val (leftObs, rightObs) = if (firstObs.horizontalAngleL != null) {
            Pair(firstObs, secondObs)
        } else {
            Pair(secondObs, firstObs)
        }

        // 计算2C互差（水平角）
        if (leftObs.horizontalAngleL != null && rightObs.horizontalAngleR != null) {
            val horizontal2C = Math.abs(leftObs.horizontalAngleL!! - (rightObs.horizontalAngleR!! + Math.PI))
            leftObs.measure2C = horizontal2C
            rightObs.measure2C = horizontal2C
        }

        // 计算2D互差（距离）
        if (leftObs.distanceL != null && rightObs.distanceR != null) {
            val distance2D = Math.abs(leftObs.distanceL!! - rightObs.distanceR!!) * 1000  // 转换为毫米
            leftObs.measure2D = distance2D
            rightObs.measure2D = distance2D
        }
    }

    /**
     * 检查观测值质量
     */
    fun checkObservationQuality(observations: List<MonitoringPointCtrlObservation>, config: MeasureConfig): Pair<Boolean, String?> {
        if (!config.needLeftRight) return true to null

        // 提取盘左和盘右观测值
        val leftObs = observations.firstOrNull { it.horizontalAngleL != null }
        val rightObs = observations.firstOrNull { it.horizontalAngleR != null }

        Log.i(TAG, "checkObservationQuality ### leftObs = ${Gson().toJson(leftObs)}")
        Log.i(TAG, "checkObservationQuality ### rightObs = ${Gson().toJson(rightObs)}")

        // 处理只测单盘位的情况
        if (leftObs == null && rightObs != null) {
            return true to null // 只测盘右，无需检查互差
        }
        if (rightObs == null && leftObs != null) {
            return true to null // 只测盘左，无需检查互差
        }

        if (leftObs == null || rightObs == null) {
            return false to "观测数据不完整"
        }

        var horizontal2C_scc : Double? = null
        var verticalDiff_scc : Double? = null
        var distanceDiff_scc : Double? = null


        // 检查水平角2C互差（秒）：加入角度周期性修正
        if (leftObs.horizontalAngleL != null && rightObs.horizontalAngleR != null) {
            val hl = leftObs.horizontalAngleL!!
            val hr = rightObs.horizontalAngleR!!

            // 计算原始差值：hl - (hr + π)
            var rawDiff = hl - (hr + Math.PI)

            // 处理角度周期性：取最小角度差（≤π）
            // 若差值绝对值 > π，则用 2π 减去该值（等价于取对边的小角度）
            if (Math.abs(rawDiff) > Math.PI) {
                rawDiff = if (rawDiff > 0) rawDiff - 2 * Math.PI else rawDiff + 2 * Math.PI
            }

            // 计算2C值（取绝对值，转换为秒）
            val horizontal2C = Math.abs(rawDiff) * MeasureConstants.RAD_TO_SEC
            Log.i(TAG, "checkObservationQuality ### 修正后horizontal2C = $horizontal2C")
            horizontal2C_scc = horizontal2C
            if (horizontal2C > config.maxHorizontal2C) {
                return false to "水平角2C互差超限: ${String.format("%.2f", horizontal2C)}秒"
            }
        }

        // 检查垂直角互差（秒）：使用之前修正的天顶距转换逻辑
        if (leftObs.verticalAngleL != null && rightObs.verticalAngleR != null) {
            val vl = leftObs.verticalAngleL!!
            var vr = rightObs.verticalAngleR!!

            // 转换盘右垂直角为实际天顶距（0~π）
            if (vr > Math.PI) {
                vr = 2 * Math.PI - vr
            }

            val verticalDiff = Math.abs(vl - vr) * MeasureConstants.RAD_TO_SEC
            Log.i(TAG, "checkObservationQuality ### verticalDiff = $verticalDiff")
            verticalDiff_scc = verticalDiff
            if (verticalDiff > config.maxVerticalDiff) {
                return false to "垂直角互差超限: ${String.format("%.2f", verticalDiff)}秒"
            }
        }

        // 检查距离互差（毫米）：逻辑正确，无需修改
        if (leftObs.distanceL != null && rightObs.distanceR != null) {
            val distanceDiff = Math.abs(leftObs.distanceL!! - rightObs.distanceR!!) * 1000
            Log.i(TAG, "checkObservationQuality ### distanceDiff = $distanceDiff")
            distanceDiff_scc = distanceDiff
            if (distanceDiff > config.maxDistanceDiff) {
                return false to "距离互差超限: ${String.format("%.2f", distanceDiff)}mm"
            }
        }

        val sb = StringBuilder()
        horizontal2C_scc?.let {
            val ss = "2C互差（秒）${String.format("%.2f", it)}秒"
            sb.append(ss)
        }

        verticalDiff_scc?.let {
            val ss = "垂直角互差（秒）${String.format("%.2f", it)}秒"
            sb.append("," + ss)
        }

        distanceDiff_scc?.let {
            val ss = "距离互差${String.format("%.2f", it)}米"
            sb.append("," + ss)
        }

        return true to sb.toString()
    }

}